///@file MeshSceneNode.cpp source file for class CMeshSceneNode
///@author	charlie Tan: gths123@gmail.com

#include "ISceneManager.h"
#include "IMyCamera.h"
#include "ITexture.h"
#include "BillboardSceneNode.h"

//! sharpShooter
namespace sharpShooter
{
	//! Scene
	namespace Scene
	{

		CBillboardSceneNode::CBillboardSceneNode(ISceneNode *parent, ISceneManager *smgr, Core::Vector3f position, Core::Vector2f size)
			:IBillboardSceneNode(parent,position),m_Size(size),m_SceneManager(smgr)
		{
			m_Indices[0].v1 = 1;
			m_Indices[0].v2 = 0;
			m_Indices[0].v3 = 2;

			m_Indices[1].v1 = 1;
			m_Indices[1].v2 = 2;
			m_Indices[1].v3 = 3;


			m_Vertices[0].UV.mX = 0.0f;
			m_Vertices[0].UV.mY = 1.0f;

			m_Vertices[1].UV.mX = 1.0f;
			m_Vertices[1].UV.mY = 1.0f;

			m_Vertices[2].UV.mX = 0.0f;
			m_Vertices[2].UV.mY = 0.0f;

			m_Vertices[3].UV.mX = 1.0f;
			m_Vertices[3].UV.mY = 0.0f;

		}

		void CBillboardSceneNode::render(/*ID3DXEffect *effect*/)
		{
			if (!m_Visible)
			{
				return;
			}
			ISceneNode::render(/*effect*/);

			Device::ISharpShooterDevice*	pDevice = m_SceneManager->getDevice();
			IMyCamera			*activeCamera = m_SceneManager->getCurrentCamera();

			Core::Vector3f		cameraPosition(activeCamera->getPosition());
			Core::Vector3f		cameraUp(activeCamera->getWorldUp());
			Core::Vector3f		cameraTarget(activeCamera->getLookAt());

			Core::Vector3f		view(cameraTarget-cameraPosition);

			view.normalize();
			Core::Vector3f		horizontal;
			horizontal = cameraUp.crossProduct(view);

			if (horizontal == Core::Vector3f(0.0f,0.0f,0.0f))
			{
				horizontal.mX = cameraUp.mY;
				horizontal.mY = cameraUp.mX;
				horizontal.mZ = cameraUp.mZ;
			}
			horizontal.normalize();

			Core::Vector3f vertical;
			vertical = horizontal.crossProduct(view);
			vertical.normalize();

			horizontal *= (float)(0.5 * m_Size.mX);
			vertical *= (float)(0.5 * m_Size.mY);


			m_Vertices[0].Position.mX = m_Position.mX - horizontal.mX + vertical.mX;
			m_Vertices[0].Position.mY = m_Position.mY - horizontal.mY + vertical.mY;
			m_Vertices[0].Position.mZ = m_Position.mZ - horizontal.mZ + vertical.mZ;

			m_Vertices[1].Position.mX = m_Position.mX + horizontal.mX + vertical.mX;
			m_Vertices[1].Position.mY = m_Position.mY + horizontal.mY + vertical.mY;
			m_Vertices[1].Position.mZ = m_Position.mZ + horizontal.mZ + vertical.mZ;

			m_Vertices[2].Position.mX = m_Position.mX - horizontal.mX - vertical.mX;
			m_Vertices[2].Position.mY = m_Position.mY - horizontal.mY - vertical.mY;
			m_Vertices[2].Position.mZ = m_Position.mZ - horizontal.mZ - vertical.mZ;

			m_Vertices[3].Position.mX = m_Position.mX + horizontal.mX - vertical.mX;
			m_Vertices[3].Position.mY = m_Position.mY + horizontal.mY - vertical.mY;
			m_Vertices[3].Position.mZ = m_Position.mZ + horizontal.mZ - vertical.mZ;

			getAABBox();
			pDevice->drawIndexedTrangleList(&m_Vertices
				,4,Render::VT_DEFAULT,&m_Indices,2,Render::E_Index32,*m_Material);
		}


		const Core::Vector2f& CBillboardSceneNode::getSize()const
		{
			return m_Size;
		}
		void CBillboardSceneNode::setSize(const Core::Vector2f& size)
		{
			m_Size = size;
		}

		void CBillboardSceneNode::calculateAABBox(void)
		{
			m_AABBox.maxX = m_Vertices[0].Position.mX;
			m_AABBox.minX = m_Vertices[0].Position.mX;

			m_AABBox.maxY = m_Vertices[0].Position.mY;
			m_AABBox.minY = m_Vertices[0].Position.mY;

			m_AABBox.maxZ = m_Vertices[0].Position.mZ;
			m_AABBox.minZ = m_Vertices[0].Position.mZ;

			for (int i = 1 ; i < 4; i++)
			{
				if (m_AABBox.maxX < m_Vertices[i].Position.mX)
				{
					m_AABBox.maxX = m_Vertices[i].Position.mX;
				}
				if (m_AABBox.minX > m_Vertices[i].Position.mX)
				{
					m_AABBox.minX = m_Vertices[i].Position.mX;
				}

				if (m_AABBox.maxY < m_Vertices[i].Position.mY)
				{
					m_AABBox.maxY = m_Vertices[i].Position.mY;
				}
				if (m_AABBox.minY > m_Vertices[i].Position.mY)
				{
					m_AABBox.minY = m_Vertices[i].Position.mY;
				}

				if (m_AABBox.maxZ < m_Vertices[i].Position.mZ)
				{
					m_AABBox.maxZ = m_Vertices[i].Position.mZ;
				}
				if (m_AABBox.minZ > m_Vertices[i].Position.mZ)
				{
					m_AABBox.minZ = m_Vertices[i].Position.mZ;
				}		
			}
		}

	}
}